
package com.feib.soeasy.service.impl;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import com.feib.soeasy.dao.MailQueueDao;
import com.feib.soeasy.dao.PaymentCanceledDao;
import com.feib.soeasy.dao.PaymentDao;
import com.feib.soeasy.dao.PaymentItemDao;
import com.feib.soeasy.dao.UploadFileDao;
import com.feib.soeasy.dao.UserDao;
import com.feib.soeasy.dao.WriteOffPaymentDao;
import com.feib.soeasy.job.MailJob;
import com.feib.soeasy.job.util.MailContentTemplate;
import com.feib.soeasy.model.FormatDefinition;
import com.feib.soeasy.model.Group;
import com.feib.soeasy.model.MailQueue;
import com.feib.soeasy.model.Payment;
import com.feib.soeasy.model.PaymentCanceled;
import com.feib.soeasy.model.PaymentItem;
import com.feib.soeasy.model.UploadFile;
import com.feib.soeasy.model.User;
import com.feib.soeasy.model.WriteOffPayment;
import com.feib.soeasy.pagination.PaginatedList;
import com.feib.soeasy.service.PaymentService;
import com.feib.soeasy.util.DateUtil;
import com.feib.soeasy.util.UserUtil;


/**
 * @title (#)PaymentServiceImpl.java<br>
 * @description 繳費單邏輯物件<br>
 * @author Jimmy Liu<br>
 * @version 1.0.0 2010/11/25
 * @copyright Far Eastern International Bank Copyright (c) 2010<br>
 * @2010/11/18 create by Jimmy Liu<br>
 */
@Service("paymentService")
public class PaymentServiceImpl extends BaseServiceImpl implements PaymentService {

	@Resource(name="writeOffPaymentDao")
	private WriteOffPaymentDao writeOffPaymentDao;

	@Resource(name="paymentDao")
	private PaymentDao paymentDao;

	@Resource(name="paymentItemDao")
	private PaymentItemDao paymentItemDao;

	@Resource(name="paymentCanceledDao")
	private PaymentCanceledDao paymentCanceledDao;

	@Resource(name="uploadFileDao")
	private UploadFileDao uploadFileDao;

	@Resource(name="userDao")
	private UserDao userDao;

	@Resource(name="mailJob")
	private MailJob mailJob;

	@Resource(name="itEmails")
	private String itEmails;

	@Resource(name="htmlMailFolder")
	private String htmlMailFolder;

	@Resource(name="defaultMailFrom")
	private String defaultMailFrom;

	@Resource(name="defaultMailReturnReceiptTo")
	private String defaultMailReturnReceiptTo;

	@Resource(name="txManager")
	private PlatformTransactionManager transactionManager;

	@Resource(name="mailQueueDao")
	private MailQueueDao mailQueueDao;


	public Payment getPaymentByPk(Payment payment)
	{
		return paymentDao.getPaymentByPk(payment);
	}

	/**
	 * @param payment
	 * @return
	 */
	public List<Payment> getPaymentByPk(List<Payment> payment)
	{
		return paymentDao.getPaymentByPk(payment);
	}

	/**
	 * 取得檔案應繳總金額
	 * @param uploadFilePk	上傳檔案檔pk 值
	 * @return 總金額
	 * @author Leo Lee
	 */
	@Override
	public Long getTotalAmountByUploadFilePk(Long uploadFilePk)
	{
		return paymentDao.getTotalAmountByUploadFilePk(uploadFilePk , null);
	}

	/**
	 * 依據查詢物件與繳費截止日期起迄查詢繳費單
	 * @param payment 查詢條件
	 * @param payDueFrom 繳費截止日期起
	 * @param payDueTo 繳費截止日期迄
	 * @param paginationConfig 換頁條件
	 * @return 查詢結果物件
	 */
	@Override
	public PaginatedList<Payment> queryByPayment(Payment payment, Date payDueFrom, Date payDueTo, PaginatedList<Payment> paginationConfig) {

		// 上傳時間查詢條件設定
		if (null != payDueFrom)
		{
			// 將時分秒設定在00:00:00
			payDueFrom = DateUtil.getInstance().getBeginOfDateTime(payDueFrom);
		}

		if (null != payDueTo)
		{
			// 將時分秒設定在23:59:59
			payDueTo = DateUtil.getInstance().getEndOfDateTime(payDueTo);
		}

		// 設定 Default 排序  uploadDate desc
		//if (StringUtils.isEmpty(paginationConfig.getSortCriterion()))
		//{
		//    paginationConfig.setSortCriterion("virtualAccount");
		//    paginationConfig.setSortDirection(PaginatedList.SORT_DIRECTION_DESC);
		//}

		return paymentDao.queryPaginationByPayment(payment, payDueFrom, payDueTo, paginationConfig);
	}

	/**
	 * 依據查詢物件與繳費截止日期起迄查詢繳費單
	 * @param payment 查詢條件
	 * @param payDueFrom 繳費截止日期起
	 * @param payDueTo 繳費截止日期迄
	 * @param paginationConfig 換頁條件
	 * @param queryType 特別判斷條件 P: 繳費查詢用
	 * @return 查詢結果物件
	 */
	@Override
	public PaginatedList<Payment> queryByPayment(
			Payment payment, Date payDueFrom, Date payDueTo, 
			PaginatedList<Payment> paginationConfig, 
			String queryType) {

		// 上傳時間查詢條件設定
		if (null != payDueFrom)
		{
			// 將時分秒設定在00:00:00
			payDueFrom = DateUtil.getInstance().getBeginOfDateTime(payDueFrom);
		}

		if (null != payDueTo)
		{
			// 將時分秒設定在23:59:59
			payDueTo = DateUtil.getInstance().getEndOfDateTime(payDueTo);
		}

		// 設定 Default 排序  uploadDate desc
		//if (StringUtils.isEmpty(paginationConfig.getSortCriterion()))
		//{
		//    paginationConfig.setSortCriterion("virtualAccount");
		//    paginationConfig.setSortDirection(PaginatedList.SORT_DIRECTION_DESC);
		//}
		if (StringUtils.isEmpty(paginationConfig.getSortCriterion()))
		{
			paginationConfig.setSortCriterion("payerId");
			paginationConfig.setSortCriterion("virtualAccount");
			paginationConfig.setSortDirection(PaginatedList.SORT_DIRECTION_DESC);
		}

		return paymentDao.queryPaginationByPayment(
				payment, payDueFrom, payDueTo, paginationConfig, queryType);
	}

	/* (non-Javadoc)
	 * @see com.feib.soeasy.service.PaymentService#queryByPayment(com.feib.soeasy.model.Payment, com.feib.soeasy.model.FormatDefinition, java.util.Date, java.util.Date, java.util.Date, java.util.Date, com.feib.soeasy.pagination.PaginatedList)
	 */
	public PaginatedList<Payment> queryByPayment(Payment payment, FormatDefinition formatDefinition
			, Date payDueFrom, Date payDueTo, Date writeOffDateFrom, Date writeOffDateTo, Date txDateFrom, Date txDateTo, PaginatedList<Payment> paginationConfig) {

		// 繳費截止日期查詢條件設定
		if (null != payDueFrom)
		{
			// 將時分秒設定在00:00:00
			payDueFrom = DateUtil.getInstance().getBeginOfDateTime(payDueFrom);
		}

		if (null != payDueTo)
		{
			// 將時分秒設定在23:59:59
			payDueTo = DateUtil.getInstance().getEndOfDateTime(payDueTo);
		}

		// 銷帳日期查詢條件設定
		if (null != writeOffDateFrom)
		{
			// 將時分秒設定在00:00:00
			writeOffDateFrom = DateUtil.getInstance().getBeginOfDateTime(writeOffDateFrom);
		}

		if (null != writeOffDateTo)
		{
			// 將時分秒設定在23:59:59
			writeOffDateTo = DateUtil.getInstance().getEndOfDateTime(writeOffDateTo);
		}

		// 實際繳款日期查詢條件設定
		if (null != txDateFrom)
		{
			// 將時分秒設定在00:00:00
			txDateFrom = DateUtil.getInstance().getBeginOfDateTime(txDateFrom);
		}

		if (null != txDateTo)
		{
			// 將時分秒設定在23:59:59
			txDateTo = DateUtil.getInstance().getEndOfDateTime(txDateTo);
		}
		//黃郁珊 依中租需求修改
		if (StringUtils.isEmpty(paginationConfig.getSortCriterion()))
		{
			paginationConfig.setSortCriterion("payerId");
			paginationConfig.setSortCriterion("virtualAccount");
			paginationConfig.setSortDirection(PaginatedList.SORT_DIRECTION_DESC);
		}
		return paymentDao.queryPaginationByPayment(
				payment, formatDefinition, payDueFrom, payDueTo, writeOffDateFrom, writeOffDateTo, txDateFrom, txDateTo, paginationConfig);
	}

	/* (non-Javadoc)
	 * @see com.feib.soeasy.service.PaymentService#queryByPaymentSql(com.feib.soeasy.model.Payment, com.feib.soeasy.model.FormatDefinition, java.util.Date, java.util.Date, java.util.Date, java.util.Date, com.feib.soeasy.pagination.PaginatedList)
	 */
	public PaginatedList<Payment> queryByPaymentSql(Payment payment, FormatDefinition formatDefinition
			, Date payDueFrom, Date payDueTo, Date writeOffDateFrom, Date writeOffDateTo, Date txDateFrom, Date txDateTo, PaginatedList<Payment> paginationConfig) {

		// 繳費截止日期查詢條件設定
		if (null != payDueFrom)
		{
			// 將時分秒設定在00:00:00
			payDueFrom = DateUtil.getInstance().getBeginOfDateTime(payDueFrom);
		}

		if (null != payDueTo)
		{
			// 將時分秒設定在23:59:59
			payDueTo = DateUtil.getInstance().getEndOfDateTime(payDueTo);
		}

		// 銷帳日期查詢條件設定
		if (null != writeOffDateFrom)
		{
			// 將時分秒設定在00:00:00
			writeOffDateFrom = DateUtil.getInstance().getBeginOfDateTime(writeOffDateFrom);
		}

		if (null != writeOffDateTo)
		{
			// 將時分秒設定在23:59:59
			writeOffDateTo = DateUtil.getInstance().getEndOfDateTime(writeOffDateTo);
		}

		// 實際繳款日期查詢條件設定
		if (null != txDateFrom)
		{
			// 將時分秒設定在00:00:00
			txDateFrom = DateUtil.getInstance().getBeginOfDateTime(txDateFrom);
		}

		if (null != txDateTo)
		{
			// 將時分秒設定在23:59:59
			txDateTo = DateUtil.getInstance().getEndOfDateTime(txDateTo);
		}
		//黃郁珊 依中租需求修改
		if (StringUtils.isEmpty(paginationConfig.getSortCriterion()))
		{
			//modify by karlchen 2012-8-8
			paginationConfig.setSortCriterion("p.payer_id");
			paginationConfig.setSortCriterion("p.virtual_account");
			paginationConfig.setSortDirection(PaginatedList.SORT_DIRECTION_DESC);
		}
		return paymentDao.queryPaginationByPaymentSql(
				payment, formatDefinition, payDueFrom, payDueTo, writeOffDateFrom, writeOffDateTo, txDateFrom, txDateTo, paginationConfig);
	}

	/**
	 * 取得檔案應該總筆數
	 * @param uploadFilePk 上傳檔案檔pk 值
	 * @return 總筆數, 若回傳為 0 則查無應繳筆數
	 * @author Leo Lee
	 */
	@Override
	public Long getCountItemByUploadFilePk(Long uploadFilePk) {
		return paymentDao.getCountItemByUploadFilePk(uploadFilePk, null);
	}


	/* (non-Javadoc)
	 * @see com.feib.soeasy.service.PaymentService#doWriteOffPaymentsOnLine(com.feib.soeasy.model.WriteOffPayment)
	 */
	@Override
	public void doWriteOffPaymentsOnLine(WriteOffPayment writeOffPayment) {

		Date now = new Date();

		writeOffPayment.setCreatedBy("ONLINEWRITEOFF");
		writeOffPayment.setCreatedDate(now);
		writeOffPayment.setUpdatedBy("ONLINEWRITEOFF");
		writeOffPayment.setUpdatedDate(now);

		writeOffPaymentDao.save(writeOffPayment);
		paymentDao.updateWriteOffPaymentStatusAs5ForOnLine(writeOffPayment);

	}

	public void doWriteOffPayments(Payment payment)
	{
		Date now = new Date();
		Payment dbPayment = getPaymentByPk(payment);

		WriteOffPayment writeOffPayment = new WriteOffPayment();
		writeOffPayment.setAmount(dbPayment.getTotalAmount());
		writeOffPayment.setPayment(dbPayment);
		writeOffPayment.setChannel(WriteOffPayment.CHANNEL_SELF);
		writeOffPayment.setWriteOffDate(now);
		writeOffPayment.setTxDate(now);
		writeOffPayment.setWriteOffUser(UserUtil.getUser());
		writeOffPayment.setWriteOffStatus(WriteOffPayment.WRITEOFF_STATUS_Z_WAITING_CONFIRM);

		writeOffPayment.setCreatedBy(UserUtil.getUserId());
		writeOffPayment.setCreatedDate(now);
		writeOffPayment.setUpdatedBy(UserUtil.getUserId());
		writeOffPayment.setUpdatedDate(now);
		writeOffPayment = writeOffPaymentDao.save(writeOffPayment);

		dbPayment.setRealPayAmount(dbPayment.getTotalAmount());
		dbPayment.setWriteOffPayment(writeOffPayment);        
		paymentDao.save(dbPayment);

		try {

			/* 發送 Mail 通知主管 */
			List<String> emails = userDao.findUserEmailByGroupMenuId(UserUtil.getUser().getGroup(), "SOEZ2005");
			if (null != emails && 0 != emails.size())
			{
				StringBuffer mailTo = new StringBuffer();
				for(String email : emails)
					mailTo.append(email).append(",");

				SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");

				String messageTile = "[全方位企業收款服務件] 您有 帳單核銷放行作業 待執行";
				StringBuffer paragraph1 = new StringBuffer();
				paragraph1.append(UserUtil.getUser().getUserName()).append(" 於 ").append(dateFormat.format(new Date()));
				paragraph1.append(" 核銷帳單 ").append(dbPayment.getVirtualAccount()).append("， 待您確認放行。");
				paragraph1.append("<br/>請您至系統確認資料內容。");
				String[] paragraphs = new String[]{"您好", paragraph1.toString(), "謝謝"};

				MailContentTemplate mailContentTemplate = new MailContentTemplate(messageTile, paragraphs, htmlMailFolder);
				MailQueue mailQueue = mailContentTemplate.createMailQueue();
				mailQueue.setMailTo(mailTo.toString());
				mailQueue.setMailFrom(defaultMailFrom);
				mailQueue.setMailReturnReceiptTo(defaultMailReturnReceiptTo);

				// 建立交易的定義，每一次都是新的 Transaction
				DefaultTransactionDefinition definition = new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
				TransactionStatus status = transactionManager.getTransaction(definition);
				try {
					mailQueueDao.save(mailQueue);
				}
				catch (Exception e2) {
					transactionManager.rollback(status);
					status = null; // roll back 不需要再呼叫 commit
					throw e2;
				}
				if (null != status)
					transactionManager.commit(status);

				// 立即發送
				logger.debug("立即發送 Mail 給  {}", itEmails);
				mailJob.execute(mailQueue.getMailQueuePk());
				mailQueue = null; // free resource
			}
		}
		catch (Exception e) {
			logger.error("", e);
		}

	}

	public Payment doPaymentCanceled(Payment payment, String cancelReason)
	{
		Payment dbPayment = this.getPaymentByPk(payment);

		PaymentCanceled paymentCanceled = new PaymentCanceled();
		paymentCanceled.setPayment(dbPayment);
		paymentCanceled.setCancelReason(cancelReason);
		paymentCanceled.setCancelUser(UserUtil.getUser());
		paymentCanceled.setCancelDate(new Date());
		paymentCanceledDao.save(paymentCanceled);        

		dbPayment.setPaymentStatus(Payment.PAYMENT_STATUS_IN_CANCELING);
		dbPayment.setPaymentCanceled(paymentCanceled);
		this.updatePayment(dbPayment);

		try {

			/* 發送 Mail 通知主管 */
			List<String> emails = userDao.findUserEmailByGroupMenuId(UserUtil.getUser().getGroup(), "SOEZ2004");
			if (null != emails && 0 != emails.size())
			{
				StringBuffer mailTo = new StringBuffer();
				for(String email : emails)
					mailTo.append(email).append(",");

				SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");

				String messageTile = "[全方位企業收款服務件] 您有 帳單註銷放行作業 待執行";
				StringBuffer paragraph1 = new StringBuffer();
				paragraph1.append(UserUtil.getUser().getUserName()).append(" 於 ").append(dateFormat.format(new Date()));
				paragraph1.append(" 註銷帳單 ").append(dbPayment.getVirtualAccount()).append("， 待您確認放行。");
				paragraph1.append("<br/>請您至系統確認資料內容。");
				String[] paragraphs = new String[]{"您好", paragraph1.toString(), "謝謝"};

				MailContentTemplate mailContentTemplate = new MailContentTemplate(messageTile, paragraphs, htmlMailFolder);
				MailQueue mailQueue = mailContentTemplate.createMailQueue();
				mailQueue.setMailTo(mailTo.toString());
				mailQueue.setMailFrom(defaultMailFrom);
				mailQueue.setMailReturnReceiptTo(defaultMailReturnReceiptTo);



				// 建立交易的定義，每一次都是新的 Transaction
				DefaultTransactionDefinition definition = new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
				TransactionStatus status = transactionManager.getTransaction(definition);
				try {
					mailQueueDao.save(mailQueue);
				}
				catch (Exception e2) {
					transactionManager.rollback(status);
					status = null; // roll back 不需要再呼叫 commit
					throw e2;
				}
				if (null != status)
					transactionManager.commit(status);

				// 立即發送
				logger.debug("立即發送 Mail 給  {}", itEmails);
				mailJob.execute(mailQueue.getMailQueuePk());
				mailQueue = null; // free resource
			}
		}
		catch (Exception e) {
			logger.error("", e);
		}



		return dbPayment;
	}

	/**
	 * 批量核銷
	 */
	public void doWriteOffPayments(List<Payment> payment, String paymentWriteOffReason, String paymentWriteOffCode)
	{
		/* 得到現在時間 */
		Date now = new Date();
		/* 得到所有要核銷賬單的詳細資料 */
		List<Payment> dbPayment = getPaymentByPk(payment);

		List<WriteOffPayment> paymentWriteOffList = new ArrayList<WriteOffPayment>();
		/* 循環遍歷,更新核銷賬單的資料 */
		for(int i = 0 ; i < dbPayment.size() ; i++){
			WriteOffPayment writeOffPayment = new WriteOffPayment();
			writeOffPayment.setAmount(dbPayment.get(i).getTotalAmount());
			writeOffPayment.setPayment(dbPayment.get(i));
			writeOffPayment.setChannel(WriteOffPayment.CHANNEL_SELF);
			writeOffPayment.setWriteOffDate(now);
			writeOffPayment.setTxDate(now);
			writeOffPayment.setWriteOffUser(UserUtil.getUser());
			writeOffPayment.setWriteOffStatus(WriteOffPayment.WRITEOFF_STATUS_Z_WAITING_CONFIRM);
			writeOffPayment.setWriteOffNote(paymentWriteOffReason);
			writeOffPayment.setWriteOffNo(paymentWriteOffCode);

			writeOffPayment.setCreatedBy(UserUtil.getUserId());
			writeOffPayment.setCreatedDate(now);
			writeOffPayment.setUpdatedBy(UserUtil.getUserId());
			writeOffPayment.setUpdatedDate(now);

			/* 更新結果放入List中 */
			paymentWriteOffList.add(writeOffPayment);
		}
		/* 批量更新核銷賬單資料 */
		this.savePaymentWriteOff(paymentWriteOffList);

		/* 循環遍歷,更新賬單狀態 */
		for (int i = 0; i < dbPayment.size(); i++) {        	
			dbPayment.get(i).setRealPayAmount(dbPayment.get(i).getTotalAmount());
			dbPayment.get(i).setWriteOffPayment(paymentWriteOffList.get(i));
		}
		/* 批量更新賬單狀態 */
		this.updatePayment(dbPayment);

		try {
			/* 循環遍歷所有賬單,每個賬單單獨發送一封MAIL */
			for (int i = 0; i < dbPayment.size(); i++) {
				/* 發送 Mail 通知主管 */
				List<String> emails = userDao.findUserEmailByGroupMenuId(UserUtil.getUser().getGroup(), "SOEZ2005");
				if (null != emails && 0 != emails.size())
				{
					StringBuffer mailTo = new StringBuffer();
					for(String email : emails)
						mailTo.append(email).append(",");

					SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");

					String messageTile = "[全方位企業收款服務件] 您有 帳單核銷放行作業 待執行";
					StringBuffer paragraph1 = new StringBuffer();
					paragraph1.append(UserUtil.getUser().getUserName()).append(" 於 ").append(dateFormat.format(new Date()));
					paragraph1.append(" 核銷帳單 ").append(dbPayment.get(i).getVirtualAccount()).append("， 待您確認放行。");
					paragraph1.append("<br/>請您至系統確認資料內容。");
					String[] paragraphs = new String[]{"您好", paragraph1.toString(), "謝謝"};

					MailContentTemplate mailContentTemplate = new MailContentTemplate(messageTile, paragraphs, htmlMailFolder);
					MailQueue mailQueue = mailContentTemplate.createMailQueue();
					mailQueue.setMailTo(mailTo.toString());
					mailQueue.setMailFrom(defaultMailFrom);
					mailQueue.setMailReturnReceiptTo(defaultMailReturnReceiptTo);

					/* 建立交易的定義，每一次都是新的 Transaction */
					DefaultTransactionDefinition definition = new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
					TransactionStatus status = transactionManager.getTransaction(definition);
					try {
						mailQueueDao.save(mailQueue);
					}
					catch (Exception e2) {
						transactionManager.rollback(status);
						/* roll back 不需要再呼叫 commit */
						status = null; 
						throw e2;
					}
					if (null != status)
						transactionManager.commit(status);

					/* 立即發送 */
					logger.debug("立即發送 Mail 給  {}", itEmails);
					mailJob.execute(mailQueue.getMailQueuePk());
					/*  free resource */
					mailQueue = null; 
				}
			}
		}
		catch (Exception e) {
			logger.error("", e);
		}

	}


	public List<Payment> doPaymentListCanceled(List<Payment> payment, String cancelReason, String cancelNo)
	{
		/* 得到所有要註銷賬單的詳細資料 */
		List<Payment> dbPayment = this.getPaymentByPk(payment);

		List<PaymentCanceled> paymentCanceledList = new ArrayList<PaymentCanceled>();
		/* 循環遍歷,更新注銷賬單的資料 */
		for(int i = 0 ; i < dbPayment.size() ; i++){
			PaymentCanceled paymentCanceled = new PaymentCanceled();
			paymentCanceled.setPayment(dbPayment.get(i));
			paymentCanceled.setCancelReason(cancelReason);
			paymentCanceled.setCancelNo(cancelNo);
			paymentCanceled.setCancelUser(UserUtil.getUser());
			paymentCanceled.setCancelDate(new Date());

			/* 更新結果放入List中 */
			paymentCanceledList.add(paymentCanceled);
		}
		/* 批量更新注銷賬單資料 */
		this.savePaymentCancel(paymentCanceledList);

		/* 循環遍歷,更新賬單狀態 */
		for (int i = 0; i < dbPayment.size(); i++) {
			dbPayment.get(i).setPaymentStatus(Payment.PAYMENT_STATUS_IN_CANCELING);
			dbPayment.get(i).setPaymentCanceled(paymentCanceledList.get(i));			
		}
		/* 批量更新賬單狀態 */
		this.updatePayment(dbPayment);

		try {
			/* 循環遍歷所有賬單,每個賬單單獨發送一封MAIL */
			for (int i = 0; i < dbPayment.size(); i++) {
				/* 發送 Mail 通知主管 */
				List<String> emails = userDao.findUserEmailByGroupMenuId(UserUtil.getUser().getGroup(), "SOEZ2004");
				if (null != emails && 0 != emails.size())
				{
					StringBuffer mailTo = new StringBuffer();
					for(String email : emails)
						mailTo.append(email).append(",");

					SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");

					String messageTile = "[全方位企業收款服務件] 您有 帳單註銷放行作業 待執行";
					StringBuffer paragraph1 = new StringBuffer();
					paragraph1.append(UserUtil.getUser().getUserName()).append(" 於 ").append(dateFormat.format(new Date()));
					paragraph1.append(" 註銷帳單 ").append(dbPayment.get(i).getVirtualAccount()).append("， 待您確認放行。");
					paragraph1.append("<br/>請您至系統確認資料內容。");
					String[] paragraphs = new String[]{"您好", paragraph1.toString(), "謝謝"};

					MailContentTemplate mailContentTemplate = new MailContentTemplate(messageTile, paragraphs, htmlMailFolder);
					MailQueue mailQueue = mailContentTemplate.createMailQueue();
					mailQueue.setMailTo(mailTo.toString());
					mailQueue.setMailFrom(defaultMailFrom);
					mailQueue.setMailReturnReceiptTo(defaultMailReturnReceiptTo);



					/* 建立交易的定義，每一次都是新的 Transaction */
					DefaultTransactionDefinition definition = new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
					TransactionStatus status = transactionManager.getTransaction(definition);
					try {
						mailQueueDao.save(mailQueue);
					}
					catch (Exception e2) {
						transactionManager.rollback(status);
						/* roll back 不需要再呼叫 commit */
						status = null; 
						throw e2;
					}
					if (null != status)
						transactionManager.commit(status);

					/* 立即發送 */
					logger.debug("立即發送 Mail 給  {}", itEmails);
					mailJob.execute(mailQueue.getMailQueuePk());
					/* free resource */
					mailQueue = null; 
				}
			}
		}
		catch (Exception e) {
			logger.error("", e);
		}
		return dbPayment;
	}


	public void updatePayment(Payment payment)
	{
		paymentDao.save(payment);
	}

	public void updatePayment(List<Payment> payment){
		if(payment != null && payment.size() > 0){
			for (int i = 0; i < payment.size(); i++) {
				paymentDao.save(payment.get(i));
			}
		}
	}

	public void savePaymentCancel(List<PaymentCanceled> paymentCanceled){
		if(paymentCanceled != null && paymentCanceled.size() > 0){
			for (int i = 0; i < paymentCanceled.size(); i++) {
				paymentCanceledDao.save(paymentCanceled.get(i));
			}
		}
	}

	public void savePaymentWriteOff(List<WriteOffPayment> writeOffPayments){
		if(writeOffPayments != null && writeOffPayments.size() > 0){
			for (int i = 0; i < writeOffPayments.size(); i++) {
				writeOffPaymentDao.save(writeOffPayments.get(i));
			}
		}
	}

	public void batchUpdatePaymentStatusByUploadFile(
			List<UploadFile> uploadFiles, User modifyUser, Integer fileStatus)
	{
		for(Iterator<UploadFile> i=uploadFiles.iterator();i.hasNext();)
		{
			UploadFile file = (UploadFile)i.next();
			if(file != null && file.getUploadFilePk() != null)
			{
				file.setFileStatus(fileStatus);
				updatePaymentStatusByUploadFile(file, modifyUser);
			}
		}
	}

	public void updatePaymentStatusByUploadFile(UploadFile uploadFile, User modifyUser)
	{
		UploadFile tempUploadFile = uploadFileDao.getUploadFileByPk(uploadFile.getUploadFilePk());
		if(uploadFile.getFileStatus().intValue() == UploadFile.FILE_STATUS_CONFIRM_OK)
		{
			tempUploadFile.setFileStatus(uploadFile.getFileStatus());
			tempUploadFile.setConfirmStatus(Boolean.TRUE);
			tempUploadFile.setConfirmUser(modifyUser);
			tempUploadFile.setConfirmDate(new Date());
			tempUploadFile.setUpdatedBy(modifyUser.getUserId());
			tempUploadFile.setUpdatedDate(new Date());

		}
		else if(uploadFile.getFileStatus().intValue() == UploadFile.FILE_STATUS_CONFIRM_NOT_OK)
		{
			tempUploadFile.setFileStatus(uploadFile.getFileStatus());
			tempUploadFile.setConfirmStatus(Boolean.FALSE);
			tempUploadFile.setConfirmUser(modifyUser);
			tempUploadFile.setConfirmDate(new Date());
			tempUploadFile.setUpdatedBy(modifyUser.getUserId());
			tempUploadFile.setUpdatedDate(new Date());              
		}
		else if(uploadFile.getFileStatus().intValue() == UploadFile.FILE_STATUS_CREATE_REPORT)
		{
			tempUploadFile.setFileStatus(uploadFile.getFileStatus());
			tempUploadFile.setUpdatedBy(modifyUser.getUserId());
			tempUploadFile.setUpdatedDate(new Date());              
		}
		uploadFileDao.save(tempUploadFile);

		Integer paymentStatus = new Integer(0);
		if(null != uploadFile)
		{
			if(uploadFile.getFileStatus().intValue() == UploadFile.FILE_STATUS_CONFIRM_OK)
			{
				paymentStatus = new Integer(2);
				paymentDao.updatePaymentStatusByUploadFilePk(paymentStatus, uploadFile);
			}
			else if(uploadFile.getFileStatus().intValue() == UploadFile.FILE_STATUS_CONFIRM_NOT_OK)
			{
				deletePaymentByUploadFile(uploadFile);
			}
		}
	}
	/**
	 * 依uploadfile pk 值整批更新繳費狀態
	 * @param paymentStatus
	 * @param uploadFile
	 */
	public void updatePaymentStatusByUploadFile(UploadFile uploadFile)
	{
		this.updatePaymentStatusByUploadFile(uploadFile, UserUtil.getUser());       
	}

	/**
	 * 依uploadfile pk 刪除payment 資料
	 * @param uploadFile
	 */
	public void deletePaymentByUploadFile(UploadFile uploadFile)
	{
		//1. 先刪除paymentitem 
		paymentItemDao.deletePaymentItemByUploadFile(uploadFile);

		//2. 再刪除payment
		paymentDao.deletePaymentByUploadFile(uploadFile);
	}

	public List<Long> queryPaymentPkByUploadFilePk(Long uploadFilePk)
	{
		return paymentDao.queryPaymentPkByUploadFilePk(uploadFilePk);
	}

	public Payment getPaymentReport(Payment payment)
	{
		Payment result = paymentDao.getPaymentByPk(payment);
		if(null != result)
		{
			String temp ;
			if(result.getPaymentItems() != null && result.getPaymentItems().size() > 0)
				temp = ((PaymentItem)(result.getPaymentItems().get(0))).getItemName();
			else
				temp = result.getGroup().getGroupNo();
		}
		return result;
	}

	/**
	 * 依paymentStatus 取回 Payment 檔
	 * @param paymentStatus
	 * @return
	 */
	@Override
	public List<Payment> queryByPaymentStatus3(Payment payment, PaginatedList<Payment> paginationConfig)
	{
		return paymentDao.queryStatus3(payment, paginationConfig);
	}

	@Override
	public List<Payment> queryByPaymentStatus2(Payment payment, PaginatedList<Payment> paginationConfig)
	{
		return paymentDao.queryStatus2(payment, paginationConfig);
	}

	public void updatePaymentStatus(ArrayList<Payment> payment,String status){
		//2: 待繳款
		if(status.equals("2")){
			//payment
			paymentDao.updatePaymentStatusAs2(payment);
			//payment_canceled
			paymentCanceledDao.updateConfirm(payment, new Boolean(false));
		}
		//4: 已註銷(不能銷帳)
		else if(status.equals("4")){
			paymentDao.updatePaymentStatusAs4(payment);
			paymentCanceledDao.updateConfirm(payment, new Boolean(true));
		}
	}
	public void updateWriteOffPaymentStatus(ArrayList<Payment> payment,String status){
		logger.info("china test service30");
		//2: 待繳款
		if(status.equals("2")){
			//payment.WRITE_OFF_PAYMENT_PK = null, REAL_PAY_AMOUNT=null
			paymentDao.updateWriteOffPaymentStatusAs2(payment);

			//write_off_payment.WRITE_OFF_STATUS = 4, CONFIRM_DATE = sysdate, CONFIRM_USER_PK
			writeOffPaymentDao.updateConfirm(payment, new Integer(4));

		}
		//5: 已繳款
		else if(status.equals("5")){

			//payment.PAYMENT_STATUS = 5
			paymentDao.updateWriteOffPaymentStatusAs5(payment);

			//write_off_payment.WRITE_OFF_STATUS = 1, CONFIRM_DATE = sysdate, CONFIRM_USER_PK
			writeOffPaymentDao.updateConfirm(payment, new Integer(1));

		}
	}

	public List<String> queryDownloadPayments(Group qryGroup,
			Date qryPayDueFrom, Date qryPayDueTo,
			String qryVirtualAccountFrom, String qryVirtualAccountTo) 
			{
		List<Payment> payments = paymentDao.queryDownloadPayments(qryGroup, qryPayDueFrom, qryPayDueTo, qryVirtualAccountFrom, qryVirtualAccountTo);
		List<String> paymentFileNames = new ArrayList<String>();
		if (null != payments && payments.size() > 0) {
			for (Iterator<Payment> i = payments.iterator(); i.hasNext();) {
				Payment payment = (Payment) i.next();
				int ck = 0;
				if(paymentFileNames.size() > 0 )
				{
					for(int op=0;op<paymentFileNames.size();op++)
					{
						String tempFileName = (String)paymentFileNames.get(op);
						if(tempFileName.equals(payment.getPdfFilePathOnServer()))
						{
							ck = 1;
						}
					}
				}
				if(ck == 0)
					paymentFileNames.add(payment.getPdfFilePathOnServer());
			}
		}

		return paymentFileNames;
			}

	public List<Payment> queryPaymentForDetailDownload(UploadFile uploadFile, Integer paymentStatus)
	{
		return paymentDao.queryByUploadFiles(uploadFile, paymentStatus);
	}

	public int countByFormatDefinitionPk(Long formatDefinitionPk)
	{
		return paymentDao.countByFormatDefinitionPk(formatDefinitionPk);
	}
	/* (non-Javadoc)
	 * @see com.feib.soeasy.service.PaymentService#doNoticeUnPayByEmail(java.util.List)
	 */
	public void doNoticeUnPayByEmail(List<Payment> checkPayment) {

		if (null != checkPayment && 0 != checkPayment.size())
		{
			SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
			DecimalFormat decimalFormat = new DecimalFormat("##,###");
			for(Payment payment: checkPayment)
			{
				if (null != payment && null != payment.getPaymentPk())
				{
					payment = this.paymentDao.findByPk(payment.getPaymentPk());

					if (Payment.PAYMENT_STATUS_IN_PAYING.equals(payment.getPaymentStatus()))
					{

						try { 

							/* 發送 Mail 通知繳款者繳款 */
							if (null != payment.getPayerEmail())
							{
								StringBuffer mailTo = new StringBuffer();
								mailTo.append(payment.getPayerEmail()).append(",");                                    

								dateFormat = new SimpleDateFormat("yyyy/MM/dd");

								// 《管理費催繳通知》
								String messageTile = "《"+payment.getPaymentName() + "催繳通知》";
								StringBuffer noticeday = new StringBuffer();
								noticeday.append("<div align=\"right\">通知日期：").append(dateFormat.format(new Date())).append("</div>");

								StringBuffer paragraph1 = new StringBuffer();  
								if (Group.GROUP_TYPE_SCHOOL.equals(payment.getGroup().getGroupType()))
								{
									paragraph1.append("<strong>").append(payment.getPayerName()).append("</strong> 先生/小姐 您好").append("<br /><br />");
								}
								else
								{
									//貴住戶 王大同 先生/小姐 您好
									// 20121107需求單變更為「王大同 先生/小姐/寶號 敬啟」
									paragraph1.append("<strong>").append(payment.getPayerName()).append("</strong> 先生/小姐/寶號 敬啟").append("<br /><br />");
								}

								StringBuffer paragraph2 = new StringBuffer();
								paragraph2.append("您尚有")
								.append(payment.getPaymentName());
								if (! Group.GROUP_TYPE_SCHOOL.equals(payment.getGroup().getGroupType()))
									paragraph2.append(StringUtils.defaultString(payment.getPeriod()));
								paragraph2.append(decimalFormat.format(payment.getTotalAmount()))
								.append("元整尚未繳納，提醒您請儘速至各代收地點補繳。如您已繳費，請您忽略本通知，")
								.append("詳細資料請洽").append(payment.getGroup().getGroupName()).append("。");

								StringBuffer paragraph3 = new StringBuffer();
								paragraph3.append("《本信件是系統自動寄發，請勿直接回覆，如有任何").append(payment.getPaymentName())
								.append("繳費問題，請洽").append(payment.getGroup().getGroupName()).append("或電")
								.append(payment.getGroup().getContactTelNo()).append("查詢》");


								StringBuffer paragraph4 = new StringBuffer();
								paragraph4.append("<div align=\"right\"><b>").append(payment.getGroup().getGroupName()).append("</b><br />")
								.append(payment.getGroup().getContactName()).append("  ").append(StringUtils.defaultString(payment.getGroup().getContactCellNo())).append("<br />")
								.append(StringUtils.defaultString(payment.getGroup().getGroupAddress())).append("</div>");




								String[] paragraphs = new String[]{noticeday.toString(), paragraph1.toString(), paragraph2.toString(), paragraph3.toString(), paragraph4.toString()};

								MailContentTemplate mailContentTemplate = new MailContentTemplate(messageTile, paragraphs, htmlMailFolder);
								MailQueue mailQueue = mailContentTemplate.createMailQueue();
								mailQueue.setMailTo(mailTo.toString());
								mailQueue.setMailFrom(defaultMailFrom);
								mailQueue.setMailReturnReceiptTo(defaultMailReturnReceiptTo);



								// 建立交易的定義，每一次都是新的 Transaction
								DefaultTransactionDefinition definition = new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
								TransactionStatus status = transactionManager.getTransaction(definition);
								try {
									mailQueueDao.save(mailQueue);
								}
								catch (Exception e2) {
									transactionManager.rollback(status);
									status = null; // roll back 不需要再呼叫 commit
									throw e2;
								}
								if (null != status)
									transactionManager.commit(status);

								// 立即發送
								logger.debug("立即發送 Mail 給  {}", itEmails);
								mailJob.execute(mailQueue.getMailQueuePk());
								mailQueue = null; // free resource
							}
						}
						catch (Exception e) {
							logger.error("", e);
						}
					}
				}
			}
		}

	}
	/* (non-Javadoc)
	 * @see com.feib.soeasy.service.PaymentService#getPaymentByVirtualAccount(java.lang.String, boolean)
	 */
	@Override
	public Payment getPaymentByVirtualAccount(String virtualAccount, boolean unPay) {
		return paymentDao.queryPaymentByVirtualAccount(virtualAccount, unPay);
	}

	public List<String> queryPayerIdByUploadFilePk(Long uploadFilePk)
	{
		return paymentDao.queryPayerIdByUploadFilePk(uploadFilePk);
	}
	public List<String> queryPaymentStatusByUploadFilePk(Long uploadFilePk)
	{
		return paymentDao.queryPaymentStatusByUploadFilePk(uploadFilePk);
	}
	@Override
	public List<Payment> queryPayementByPayerId(String payerId, Long uploadFilePk) 
	{
		return paymentDao.queryPayementByPayerId(payerId, uploadFilePk);
	}
	@Override
	public int getPaymentByGroup_type(String virtualAccount)
	{
		return paymentDao.getPaymentByGroup_type(virtualAccount);
	}

	/**
	 * 查詢繳費單明細以便下載
	 * @author Jeff Gu
	 */
	@Override
	public List<Payment> queryDownloadPayments(Payment payment,
			Date qryPayDueFrom, Date qryPayDueTo, String qryVirtualAccountFrom,
			String qryVirtualAccountTo) {
		return paymentDao.queryDownloadPayments(payment, qryPayDueFrom, qryPayDueTo, qryVirtualAccountFrom, qryVirtualAccountTo);

	}

	@Override
	public List<Map<String, Object>> querySumByPayment(Payment payment,
			FormatDefinition formatDefinition, Date payDueFrom, Date payDueTo,
			Date writeOffDateFrom, Date writeOffDateTo, Date txDateFrom,
			Date txDateTo) {

		/* 查詢結果(已照繳費狀態處理)*/
		List<Map<String, Object>> query=paymentDao.querySumByPaymentSql(payment, formatDefinition, payDueFrom, payDueTo, writeOffDateFrom, writeOffDateTo, txDateFrom, txDateTo);

		/* 要回傳的結果(要處理畫面順序) */
		List<Map<String, Object>> result=new ArrayList<Map<String, Object>>();	

		Long totalAmount=new Long(0);
		int  count=0;

		String name[]={"全部","已繳款","待繳款","逾  期","註銷中","已註銷",};

		/* 畫面順序 */
		Map<String, Integer> showIndex=new   HashMap<String, Integer> ();		
		showIndex.put("5", 1);//已繳款		
		showIndex.put("2", 2);//待繳款
		showIndex.put("6", 3);//逾  期              
		showIndex.put("4", 5);//已註銷
		showIndex.put("3", 4);//註銷中

		/* 畫面上顯示總計 */

		if (null != query && 0 != query.size())
		{
			if(null == payment.getPaymentStatus()){

				/* 照畫面順序塞 */
				for(int i=0;i<=5;i++){
					Map<String, Object> total=new   HashMap<String, Object> ();
					total.put("total_amount", 0);
					total.put("count", 0);
					total.put("payment_Status", 0);
					total.put("payment_Status_Name", name[i]);
					result.add(i,total);
				}

				/* 當接下來的檔案撈出e-mail的時候，就去抓有沒有符合的key，有就把vaule取出加進去，沒有就重新建一個新的。*/
				for(Map<String, Object> map : query){	
					/* 總計金額 */
					String tempTotalAmount = map.get("total_amount") == null ? null : map.get("total_amount").toString();
					if(StringUtils.isNotEmpty(tempTotalAmount)){
						try {
							totalAmount += Long.valueOf(tempTotalAmount);

						} catch (Exception e) {
							logger.debug("轉型totalAmount時出錯: " + e);
						}
					}
					String tempCount = map.get("count") == null ? null : map.get("count").toString();
					if(StringUtils.isNotEmpty(tempCount)){
						try {
							count += Integer.valueOf(tempCount);

						} catch (Exception e) {
							logger.debug("轉型count時出錯: " + e);
						}
					}

					String paymentStatus = map.get("payment_Status") == null ? null : map.get("payment_Status").toString();

					if(StringUtils.isNotEmpty(paymentStatus)){
						result.get(showIndex.get(paymentStatus)).put("total_amount",tempTotalAmount);
						result.get(showIndex.get(paymentStatus)).put("count", tempCount);
						result.get(showIndex.get(paymentStatus)).put("payment_Status", paymentStatus);

					}

				}

				/* 總計 */
				result.get(0).put("total_amount",totalAmount);
				result.get(0).put("count", count);
				result.get(0).put("payment_Status", "all");

			}else{

				/* 只算一筆 */
				BigDecimal tempTotalAmount =  (BigDecimal) (query.get(0).get("total_amount") == null ? 0 : (query.get(0).get("total_amount")));			
				int tempCount = (Integer) (query.get(0).get("count") == null ? 0 : query.get(0).get("count"));				
				int paymentStatus = (Integer) (query.get(0).get("payment_Status") == null ? null : query.get(0).get("payment_Status"));

				logger.debug("paymentStatus {}",paymentStatus);

				Map<String, Object> total=new   HashMap<String, Object> ();
				total.put("total_amount", tempTotalAmount);
				total.put("count", tempCount);
				total.put("payment_Status", paymentStatus);
				total.put("payment_Status_Name", name[showIndex.get( String.valueOf(paymentStatus))]);
				result.add(0,total);
			}

		}//!=null

		return result;



	}

	@Override
	public PaginatedList<Payment> queryDelayPaymentBySql(Payment payment,
			FormatDefinition formatDefinition, Date payDueFrom, Date payDueTo,
			Date writeOffDateFrom, Date writeOffDateTo, Date txDateFrom,
			Date txDateTo, PaginatedList<Payment> paginationConfig,boolean isSchool, int delayCount) {
		// TODO Auto-generated method stub
		// 繳費截止日期查詢條件設定
		if (null != payDueFrom)
		{
			// 將時分秒設定在00:00:00
			payDueFrom = DateUtil.getBeginOfDateTime(payDueFrom);
		}

		if (null != payDueTo)
		{
			// 將時分秒設定在23:59:59
			payDueTo = DateUtil.getEndOfDateTime(payDueTo);
		}

		// 銷帳日期查詢條件設定
		if (null != writeOffDateFrom)
		{
			// 將時分秒設定在00:00:00
			writeOffDateFrom = DateUtil.getBeginOfDateTime(writeOffDateFrom);
		}

		if (null != writeOffDateTo)
		{
			// 將時分秒設定在23:59:59
			writeOffDateTo = DateUtil.getEndOfDateTime(writeOffDateTo);
		}

		// 實際繳款日期查詢條件設定
		if (null != txDateFrom)
		{
			// 將時分秒設定在00:00:00
			txDateFrom = DateUtil.getBeginOfDateTime(txDateFrom);
		}

		if (null != txDateTo)
		{
			// 將時分秒設定在23:59:59
			txDateTo = DateUtil.getEndOfDateTime(txDateTo);
		}

		if (StringUtils.isEmpty(paginationConfig.getSortCriterion()))
		{	
			paginationConfig.setSortCriterion("p.payer_id");
			paginationConfig.setSortCriterion("p.virtual_account");
			paginationConfig.setSortDirection(PaginatedList.SORT_DIRECTION_DESC);
		}
		return paymentDao.queryDelayPaymentPaginationBySql(
				payment, formatDefinition, payDueFrom, payDueTo, writeOffDateFrom, writeOffDateTo, txDateFrom, txDateTo, paginationConfig, isSchool,  delayCount);

	}

	@Override
	public List<Map<String,Object>> querySumDelayPayment(Payment payment,
			FormatDefinition formatDefinition, Date payDueFrom, Date payDueTo,
			Date writeOffDateFrom, Date writeOffDateTo, Date txDateFrom,
			Date txDateTo, boolean isSchool, int delayCount) {
		// TODO Auto-generated method stub
		/* 查詢結果(已照繳費狀態處理)*/
		List<Map<String, Object>> query=paymentDao.queryDelaySumByPaymentSql(payment, formatDefinition, payDueFrom, payDueTo, writeOffDateFrom, writeOffDateTo, txDateFrom, txDateTo, isSchool, delayCount);

		/* 要回傳的結果(要處理畫面順序) */
		List<Map<String, Object>> result=new ArrayList<Map<String, Object>>();	

		Long totalAmount=new Long(0);
		int  count=0;

		String name[]={"全部","已繳款","待繳款","逾  期","註銷中","已註銷",};

		/* 畫面順序 */
		Map<String, Integer> showIndex=new   HashMap<String, Integer> ();		
		showIndex.put("5", 1);//已繳款		
		showIndex.put("2", 2);//待繳款
		showIndex.put("6", 3);//逾  期              
		showIndex.put("4", 5);//已註銷
		showIndex.put("3", 4);//註銷中

		/* 照畫面順序塞 */
		for(int i=0;i<=5;i++){
			Map<String, Object> total=new   HashMap<String, Object> ();
			total.put("total_amount", 0);
			total.put("count", 0);
			total.put("payment_Status", 0);
			total.put("payment_Status_Name", name[i]);
			result.add(i,total);
		}

		/* 畫面上顯示總計 */

		if (null != query && 0 != query.size())
		{
		//	if (null == payment.getPaymentStatus())
		//	{
			/* 當接下來的檔案撈出e-mail的時候，就去抓有沒有符合的key，有就把vaule取出加進去，沒有就重新建一個新的。*/
			for(Map<String, Object> map : query){	
				/* 總計金額 */
				String tempTotalAmount = map.get("total_amount") == null ? null : map.get("total_amount").toString();
				if(StringUtils.isNotEmpty(tempTotalAmount)){
					try {
						totalAmount += Long.valueOf(tempTotalAmount);

					} catch (Exception e) {
						logger.debug("轉型totalAmount時出錯: " + e);
					}
				}
				String tempCount = map.get("count") == null ? null : map.get("count").toString();
				if(StringUtils.isNotEmpty(tempCount)){
					try {
						count += Integer.valueOf(tempCount);

					} catch (Exception e) {
						logger.debug("轉型count時出錯: " + e);
					}
				}

				String paymentStatus = map.get("payment_Status") == null ? null : map.get("payment_Status").toString();

				if(StringUtils.isNotEmpty(paymentStatus)){
					result.get(showIndex.get(paymentStatus)).put("total_amount",tempTotalAmount);
					result.get(showIndex.get(paymentStatus)).put("count", tempCount);
					result.get(showIndex.get(paymentStatus)).put("payment_Status", paymentStatus);

				}

			}

			/* 總計 */
			result.get(0).put("total_amount",totalAmount);
			result.get(0).put("count", count);
			result.get(0).put("payment_Status", "all");
		//}
		/*	else{

				 只算一筆 
				BigDecimal tempTotalAmount =  (BigDecimal) (query.get(0).get("total_amount") == null ? 0 : (query.get(0).get("total_amount")));			
				int tempCount = (Integer) (query.get(0).get("count") == null ? 0 : query.get(0).get("count"));				
				int paymentStatus = (Integer) (query.get(0).get("payment_Status") == null ? null : query.get(0).get("payment_Status"));

				logger.debug("paymentStatus {}",paymentStatus);

				Map<String, Object> total=new   HashMap<String, Object> ();
				total.put("total_amount", tempTotalAmount);
				total.put("count", tempCount);
				total.put("payment_Status", paymentStatus);
				total.put("payment_Status_Name", name[showIndex.get( String.valueOf(paymentStatus))]);
				result.add(0,total);
			}*/

		}//!=null

		return result;

	}





}
